Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge development dev bbob noisy #2239

Closed
wants to merge 64 commits into from

Conversation

lorenzo-consoli
Copy link
Contributor

No description provided.

lorenzo-consoli and others added 30 commits August 1, 2023 17:20
Added the f_sphere_gaussian.c file, which implements the sphere function with gaussian noise (and customable noise variance, for either moderate level or strong level of noise). The file contains the implementations of f_sphere_gaussian_raw, f_sphere_gaussian_evaluate, f_sphere_gaussian_evaluate_gradient,f_sphere_gaussian_allocate and f_sphere_gaussian_bbob_problem_allocate. In order to implement these functions, we slightly modified the coco_problem_s structure and added three new attributes: random_seed (uint_32, the random seed for generating samples from given distributions), distribution_theta (*double, the parameters of the distributions from which the noise is sampled) and last_noise_value(double, the noise value obtained from the last function evaluation. Used to compute the gradient at a given point with the same noise as the function evaluation it follows. The correct functioning of this is based on the assumption that the gradient is computed after each function evaluation). We also added the coco_noisy_problem_allocate_from_scalars function in the coco_problem.c file, which is basically a wrapper around the coco_problem_allocate_from_scalars function, which also allocates the random_seed and distribution_theta arguments mentioned before.
Added the f_sphere_gaussian.c file, which implements the sphere function with gaussian noise (and customable noise variance, for either moderate level or strong level of noise). The file contains the implementations of f_sphere_gaussian_raw, f_sphere_gaussian_evaluate, f_sphere_gaussian_evaluate_gradient,f_sphere_gaussian_allocate and f_sphere_gaussian_bbob_problem_allocate. In order to implement these functions, we slightly modified the coco_problem_s structure and added three new attributes: random_seed (uint_32, the random seed for generating samples from given distributions), distribution_theta (*double, the parameters of the distributions from which the noise is sampled) and last_noise_value(double, the noise value obtained from the last function evaluation. Used to compute the gradient at a given point with the same noise as the function evaluation it follows. The correct functioning of this is based on the assumption that the gradient is computed after each function evaluation). We also added the coco_noisy_problem_allocate_from_scalars function in the coco_problem.c file, which is basically a wrapper around the coco_problem_allocate_from_scalars function, which also allocates the random_seed and distribution_theta arguments mentioned before. EDIT: Added some missing semi-columns that I forgot around...
…_noise_value and added coco_problem_sample_gaussian function to generate normal noises.

* ```/coco/code-experiments/src/coco.h```
* ```/coco/code-experiments/src/coco_problem.c```
* ```/coco/code-experiments/src/f_sphere_gaussian.c```

Added all the new getters for the new `coco_problem_s` members (more specifically `coco_problem_get_random_seed`, `coco_problem_get_distribution_theta`, `coco_problem_get_last_noise_value`). Their signat>
The approach previously undertaken is highly unpractical and unfeasible. So I decided to change the approach
and create a wrap around the standard problems and use it to implement the bbob-noisy test suite.
The present commit implements the wrappers around the f_<function_name>_evaluate, f_<function_name>__allocate and f_<function_name>_bbob_problem_allocate functions,
needed to implement a noisy version of the given problem.

In particular, this is handled by the three functions:

* coco_problem_f_evaluate_wrap_noisy
* coco_problem_allocate_f_wrap_noisy
* coco_problem_allocate_bbob_wrap_noisy

The definition of the just mentioned functions is written in the suite_bbob_noisy_uitilities file, while their declaration is in the coco.h header file.

In order to make this idea of wrapping work, we defined the following structures

* coco_noise_model_s
* coco_noisy_problem_s

The coco_noise_model_s is used to evaluate the noise model according to the paper <paper_name>.

The coco_noisy_problem_s is a structure used as a wrapper around coco_problem_t (which is one of its member attributes, inner_problem), and is (should be) able to
implement the noisy version of a given problem in the bbob test suite.

The preceding approach of defining the noisy version of each function is, as we mentioned in the previous commit message, unfeasible.

On the other hand, for respecting the project structure in terms of protection and isolation of certain files, we found the need to define, finally, the three functions
used to allocate the noisy version of the problems in the bbob datasuite, according to the three aforementioned noise models. These functions are:

* coco_problem_allocate_bbob_wrap_noisy_gaussian
* coco_problem_allocate_bbob_wrap_noisy_uniform
* coco_problem_allocate_bbob_wrap_noisy_cauchy
… bbob_noisy.c file containing the definition of the functions needed to create and allocate the bbob-noisy test suite
This is due to the fact that the functions f_schaffers_bbob_problem_allocate
and f_gallagher_bbob_problem_allocate have a different signature than the other
f_<function_name>_bbob_problem_allocate ones.
For how I was thinking of implementing the noisy suite, as a wrap around the existing bbob suite,
this fact created the need to define specific wrappers (and function types) for these two mentioned
functions.
In addition, we added some other function type in coco_internal.h for minimizing the number of
unused parameters in the overall project
Apparently it kinda works now, it's time to do the needed tests
Generated data for regression test for the BBOB NOISY datasuite
Done the necessary modifications needed to be able to test the new implementation of the bbob-noisy
test suite against the old code.

Running now the full checks. I already checked if the fopt and the xopt are the same across the two implementations,
and this seems to be the case. Writing now the scripts to be able to reproduce the results.

One thing I observed regarding the fact that these tests were not passing at all, is that I realized that the
function id needs to exactly match across the two implementations for the xopt and yopt to be computed in the same way.

This is what I did and, as expected, it corrected this behaviour.
I am currently proceeding with the regression tests.
I tested the new implementation (in the noise free version), against the legacy code (by taking the ftrue values instead of the fval ones, noise free again)
The test consisted in randomly sampling a set of x coordinates from the legacy code and evaluate it both on the old and the new implementation.

Before doing so I tested all the optimal values, which worked (the values are the same as for the previous implementation).

For what concerns the results of the regression tests (still on the noise free version), all the tests passed except for F116 F117 F118 (ellipsoid) and F126 F127 F128 (griewank-rosenborg).

This is probably due to some differences in the inner implementation of the functions across the two versions of the coco platform, but I am still trying to figure it out...

The next step (once all test will pass for the noise-free versions), will be to check if the noisy version of the suite yields the same results as well, but now Im currently facing some problems, as the
distributions parameters for sampling the noise are not correctly allocated (or correctly passed to the sampling function), but I dont know for sure yet.
Maybe I should use the rotated version, as the legACY code computes a rotation on it
Basically there were some parameters of the objective functions that were passed as variables or literals
and were supposed to be different across the noisy and the noise free implementation, according to the
legacy code

Example.: Default conditioning for ellipsoid was 1.0e6, which is correct for the noise free functions
but not for the noisy version, since for the legacy code the conditioning of noisy problem was just 1.0e4.
There was a similar issue with the Griewank-Rosenbrock function.

This modifications required slightly ones also in the other suites calling the allocators for those functions (to be able to pass them the correct value of the argument).
Hopefully, these modifications should not alterate the already existing behaviour of the other suites, but we'll see when the tests done at commit time are done.
Passed the regression test against the legacy code and generated regression test data

1) Cleaning the code further.

1.1) Removed all the declarations that didn't need to be public from the `coco.h` file
1.2) Now the random seed is handles as a global variable (as in the legacy code), so there's no need to pass it as argument for the bbob_noisy problem allocator or as attribute of the noise model
1.3) Passing the noise model as argument to the constructor so that we'll only have one for the three different noise models

2) Modifying the test.

The randomness of the bbob noisy test suite implied the necessity to think about some sort of reproducibility between the runs.
Currently, the structure of the code emulates the legacy code-base, with the random seed defined as a global variable that is increased each time a noise term is sampled.
Thus, in order to obtain the same results over different runs, the order of evaluation must remain unaltered. As the regression data didn't previously store any
information about the order of evaluation (only for the functions, not for the x datapoints), this created the need to modify the way the regression data was created,
in order to store information about the order of eevaluation of the datapoints.
I then uploaded, in the modified format, the generated data (only for the bbob-noisy test suite) to the regression-data github repository of the numbbo organization.
This required some modifications for the script actually running the test, but, if I didn't make any mistake, it should work as well for the older format.
I added the interface for getting the last noise value for debugging, but removed such function from the source code once not needed, but forgot to remove it from the inetrface
…rc code by writing functions for allocating the distributon theta array for each distribution
@lorenzo-consoli
Copy link
Contributor Author

I think I managed to fixed the issue, I also reviewed your comments @olafmersmann. I'll try to clean the commit history now, shall we close the PR in case I manage to do this history cleanup?

@olafmersmann
Copy link
Contributor

I think I managed to fixed the issue

Great!

I'll try to clean the commit history now, shall we close the PR in case I manage to do this history cleanup?

You can either open a new PR or force-push to this one once the history is cleaned up.

def test_multiple_parameters():
for n in [1, 2, 10, 100, 200]:
fn = BenchmarkFunction("bbob", 1, 4, 1)
X = np.random.uniform(-5, 5, size=(n, 4))
y = fn(X)
assert len(y) == n
assert np.all(y >= fn.best_value())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, please don't drop tests to fix this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for before, I got confused becau

se I remember to have written a getter function for the best value which I needed for debugging, but I wasn't supposed to write/expose (issue #2219). I kinda forgot after a while and must have thought that this function was coco_problem_get_best_value, so I deleted it. Of course this was not the case as this function was already there well before I started to work on this, and the function was another one coco_problem_get_best_decision_vector, which can be found somewhere in the commit history of the dev-bbob-noisy branch and this caused my confusion.... Indeed I was very of surprised of seeing that function again,
(actually, if I think about it now, that wouldn't have even been possible actually), before realizing that it was just another one... Silly me!!

Anyway, now it should hopefully work because I pasted the coco_get_best_value (and reverted the silly changes I did). Thank you, we will see in some minutes. Please, let me know if it is good now

olafmersmann and others added 16 commits November 22, 2023 22:42
Since switching away from do.yp to scripts/fabricate, the developer
experience has changed drastically. This commit starts adding more
formal documentation on how a developer interacts with the code
base.

Resolves #2230
Partially fixes #2238
It remains in some doctests, because filter bails on Windows tests
…h with the development branch

First Commit working on the bbob-noisy suite

Added the f_sphere_gaussian.c file, which implements the sphere function with gaussian noise (and customable noise variance, for either moderate level or strong level of noise). The file contains the implementations of f_sphere_gaussian_raw, f_sphere_gaussian_evaluate, f_sphere_gaussian_evaluate_gradient,f_sphere_gaussian_allocate and f_sphere_gaussian_bbob_problem_allocate. In order to implement these functions, we slightly modified the coco_problem_s structure and added three new attributes: random_seed (uint_32, the random seed for generating samples from given distributions), distribution_theta (*double, the parameters of the distributions from which the noise is sampled) and last_noise_value(double, the noise value obtained from the last function evaluation. Used to compute the gradient at a given point with the same noise as the function evaluation it follows. The correct functioning of this is based on the assumption that the gradient is computed after each function evaluation). We also added the coco_noisy_problem_allocate_from_scalars function in the coco_problem.c file, which is basically a wrapper around the coco_problem_allocate_from_scalars function, which also allocates the random_seed and distribution_theta arguments mentioned before.

First Commit working on the bbob-noisy suite

Added the f_sphere_gaussian.c file, which implements the sphere function with gaussian noise (and customable noise variance, for either moderate level or strong level of noise). The file contains the implementations of f_sphere_gaussian_raw, f_sphere_gaussian_evaluate, f_sphere_gaussian_evaluate_gradient,f_sphere_gaussian_allocate and f_sphere_gaussian_bbob_problem_allocate. In order to implement these functions, we slightly modified the coco_problem_s structure and added three new attributes: random_seed (uint_32, the random seed for generating samples from given distributions), distribution_theta (*double, the parameters of the distributions from which the noise is sampled) and last_noise_value(double, the noise value obtained from the last function evaluation. Used to compute the gradient at a given point with the same noise as the function evaluation it follows. The correct functioning of this is based on the assumption that the gradient is computed after each function evaluation). We also added the coco_noisy_problem_allocate_from_scalars function in the coco_problem.c file, which is basically a wrapper around the coco_problem_allocate_from_scalars function, which also allocates the random_seed and distribution_theta arguments mentioned before. EDIT: Added some missing semi-columns that I forgot around...

Writing getter functions for random_seed, distribution_theta and last_noise_value and added coco_problem_sample_gaussian function to generate normal noises.

* ```/coco/code-experiments/src/coco.h```
* ```/coco/code-experiments/src/coco_problem.c```
* ```/coco/code-experiments/src/f_sphere_gaussian.c```

Added all the new getters for the new `coco_problem_s` members (more specifically `coco_problem_get_random_seed`, `coco_problem_get_distribution_theta`, `coco_problem_get_last_noise_value`). Their signat>

Defining the functions for the uniform noise model and implementing the sphere with uniform noise

Implementing the functions for sampling following the cauchy noise model

Changing approach

The approach previously undertaken is highly unpractical and unfeasible. So I decided to change the approach
and create a wrap around the standard problems and use it to implement the bbob-noisy test suite.
The present commit implements the wrappers around the f_<function_name>_evaluate, f_<function_name>__allocate and f_<function_name>_bbob_problem_allocate functions,
needed to implement a noisy version of the given problem.

In particular, this is handled by the three functions:

* coco_problem_f_evaluate_wrap_noisy
* coco_problem_allocate_f_wrap_noisy
* coco_problem_allocate_bbob_wrap_noisy

The definition of the just mentioned functions is written in the suite_bbob_noisy_uitilities file, while their declaration is in the coco.h header file.

In order to make this idea of wrapping work, we defined the following structures

* coco_noise_model_s
* coco_noisy_problem_s

The coco_noise_model_s is used to evaluate the noise model according to the paper <paper_name>.

The coco_noisy_problem_s is a structure used as a wrapper around coco_problem_t (which is one of its member attributes, inner_problem), and is (should be) able to
implement the noisy version of a given problem in the bbob test suite.

The preceding approach of defining the noisy version of each function is, as we mentioned in the previous commit message, unfeasible.

On the other hand, for respecting the project structure in terms of protection and isolation of certain files, we found the need to define, finally, the three functions
used to allocate the noisy version of the problems in the bbob datasuite, according to the three aforementioned noise models. These functions are:

* coco_problem_allocate_bbob_wrap_noisy_gaussian
* coco_problem_allocate_bbob_wrap_noisy_uniform
* coco_problem_allocate_bbob_wrap_noisy_cauchy

Corrected a few bugs I noticed from the previous commit and added the bbob_noisy.c file containing the definition of the functions needed to create and allocate the bbob-noisy test suite

Testing the c code build and running the first (unsuccessfull) regression test.

Array initialization was wrong

Need to handle the schaffers and gallagher functions in a particular way

This is due to the fact that the functions f_schaffers_bbob_problem_allocate
and f_gallagher_bbob_problem_allocate have a different signature than the other
f_<function_name>_bbob_problem_allocate ones.
For how I was thinking of implementing the noisy suite, as a wrap around the existing bbob suite,
this fact created the need to define specific wrappers (and function types) for these two mentioned
functions.
In addition, we added some other function type in coco_internal.h for minimizing the number of
unused parameters in the overall project

Generating data for regression test for the bbob-noisy suite

Apparently it kinda works now, it's time to do the needed tests

Preparing code for regression testing

Done the necessary modifications needed to be able to test the new implementation of the bbob-noisy
test suite against the old code.

Running now the full checks. I already checked if the fopt and the xopt are the same across the two implementations,
and this seems to be the case. Writing now the scripts to be able to reproduce the results.

One thing I observed regarding the fact that these tests were not passing at all, is that I realized that the
function id needs to exactly match across the two implementations for the xopt and yopt to be computed in the same way.

This is what I did and, as expected, it corrected this behaviour.

Proceeding with the regression test

I am currently proceeding with the regression tests.
I tested the new implementation (in the noise free version), against the legacy code (by taking the ftrue values instead of the fval ones, noise free again)
The test consisted in randomly sampling a set of x coordinates from the legacy code and evaluate it both on the old and the new implementation.

Before doing so I tested all the optimal values, which worked (the values are the same as for the previous implementation).

For what concerns the results of the regression tests (still on the noise free version), all the tests passed except for F116 F117 F118 (ellipsoid) and F126 F127 F128 (griewank-rosenborg).

This is probably due to some differences in the inner implementation of the functions across the two versions of the coco platform, but I am still trying to figure it out...

The next step (once all test will pass for the noise-free versions), will be to check if the noisy version of the suite yields the same results as well, but now Im currently facing some problems, as the
distributions parameters for sampling the noise are not correctly allocated (or correctly passed to the sampling function), but I dont know for sure yet.

Having problems with Ellipsoid

Maybe I should use the rotated version, as the legACY code computes a rotation on it

Solved issue with Griewank-Rosenbrock and Ellipsoid function

Basically there were some parameters of the objective functions that were passed as variables or literals
and were supposed to be different across the noisy and the noise free implementation, according to the
legacy code

Example.: Default conditioning for ellipsoid was 1.0e6, which is correct for the noise free functions
but not for the noisy version, since for the legacy code the conditioning of noisy problem was just 1.0e4.
There was a similar issue with the Griewank-Rosenbrock function.

This modifications required slightly ones also in the other suites calling the allocators for those functions (to be able to pass them the correct value of the argument).
Hopefully, these modifications should not alterate the already existing behaviour of the other suites, but we'll see when the tests done at commit time are done.

Regression test completed

Cleaning the code

Regression test passed (Hopefully)

Passed the regression test against the legacy code and generated regression test data

1) Cleaning the code further.

1.1) Removed all the declarations that didn't need to be public from the `coco.h` file
1.2) Now the random seed is handles as a global variable (as in the legacy code), so there's no need to pass it as argument for the bbob_noisy problem allocator or as attribute of the noise model
1.3) Passing the noise model as argument to the constructor so that we'll only have one for the three different noise models

2) Modifying the test.

The randomness of the bbob noisy test suite implied the necessity to think about some sort of reproducibility between the runs.
Currently, the structure of the code emulates the legacy code-base, with the random seed defined as a global variable that is increased each time a noise term is sampled.
Thus, in order to obtain the same results over different runs, the order of evaluation must remain unaltered. As the regression data didn't previously store any
information about the order of evaluation (only for the functions, not for the x datapoints), this created the need to modify the way the regression data was created,
in order to store information about the order of eevaluation of the datapoints.
I then uploaded, in the modified format, the generated data (only for the bbob-noisy test suite) to the regression-data github repository of the numbbo organization.
This required some modifications for the script actually running the test, but, if I didn't make any mistake, it should work as well for the older format.

Minor mistake in commit

Still some minor fixes to the commit

Problem with the python interface.

I added the interface for getting the last noise value for debugging, but removed such function from the source code once not needed, but forgot to remove it from the inetrface

Still some minor fixes to the commit (python interface)

Cleaning the code

Error in the file testing the bbob-noisy suite against the legacy code

Updating comments to the code

Started to play around with the pycma package and cleaned a bit the src code by writing functions for allocating the distributon theta array for each distribution

Fixing issue with indexing of problems, function and other stuff

Adding best_decision_vector to the python interface

Cleaning up before PR, Removing unnecessary files

This should be the "final" commit, in the sense that it is the first commit where the results obtained
are exactly the same as the one for the legacy code.
Before I forgot to implement the boundary handling method that were adding a penalty on the decision vector.

Hopefully this is the right time, but I guess we'll have to see the results of the tests done at commit time

Removing printf statemets after debugging

Passing structures as void *

Changing the allocation of the noisy problems

removing python interface to best values/parameters

The signature of the coco_suite_allocate function changed, need to update it on the suite_bbob_noisy.c file as well, I hope this is the only reason why the tests have not passed in the first commit after the merge, but I guess that only time will tell us
Patching after review, history should now be clean and ready for the final merge
@lorenzo-consoli
Copy link
Contributor Author

Should be good now, could you confirm please ? Sorry for having wasted your time before... Thank you @olafmersmann

@nikohansen
Copy link
Contributor

I suggest to

  • remove the last merge commit
  • squash everything to very few commits, say, below 10, where the example experiment should be a separate commit, adaptations/changes of the logger/observer should be a separate commit... When an intermediary merge commit cannot easily be removed, it may be practical to just keep these too.
  • rebase on the development branch (if possible)

@lorenzo-consoli
Copy link
Contributor Author

Hello,
I hope you are doing good.
If you want to finish with this, please let me know. I am available any time to join you for a call if needed. Thank you and best regards.

@brockho
Copy link
Contributor

brockho commented Jan 25, 2024

Hello, I hope you are doing good. If you want to finish with this, please let me know. I am available any time to join you for a call if needed. Thank you and best regards.

Dear Lorenzo,

Sorry for not replying earlier. We have not yet resumed our weekly BBOB/COCO meeting. We will meet next Thursday for the first time this year.

@lorenzo-consoli
Copy link
Contributor Author

Hello,

Sorry for not replying earlier, I have tried to contact you privately but I guess you didn't see my messages. I am available anytime to work with you for completing the merge. I haven't done this before because I am not 100% comfortable with altering the commit history on my own, I am sorry for that.
Thank you,

Lorenzo

@olafmersmann
Copy link
Contributor

Merged by rebasing on top of current development branch.

Thanks for you effort and patience!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants